package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.mapper.RoleResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.StringUtils;
import com.zzyl.vo.ResourceVo;
import com.zzyl.vo.TreeItemVo;
import com.zzyl.vo.TreeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 权限表业务接口实现类
 */

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private RoleResourceMapper roleResourceMapper;

    /**
     * 多条件查询资源列表
     * @param resourceDto 查询条件
     */
    @Override
    public List<ResourceVo> getList(ResourceDto resourceDto) {
        List<Resource> list = resourceMapper.selcctList(resourceDto);
        return BeanUtil.copyToList(list, ResourceVo.class);
    }

    /**
     * 资源树形
     * @param resourceDto 查询条件
     */
    @Override
    public TreeVo resourceTreeVo(ResourceDto resourceDto) {
        //1、构建查询条件
        ResourceDto dto = ResourceDto.builder()
                .dataState(SuperConstant.DATA_STATE_0)  // 数据状态：0-正常
                .parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID)) // 父编号：100001
                .resourceType(SuperConstant.MENU)  // 资源类型：m-菜单
                .build();
        //2、查询所有资源数据
        List<Resource> resourceList = resourceMapper.selcctList(dto);
        if(EmptyUtil.isNullOrEmpty(resourceList)){
            throw new RuntimeException("资源信息未定义");
        }
        //3、没有根节点，构建根节点
        Resource rootResource = new Resource();
        rootResource.setResourceNo(SuperConstant.ROOT_PARENT_ID); // 编号：100001000000000
        rootResource.setResourceName("智慧养老院"); //资源名：智慧养老院

        //4、用于返回的树形集合
        List<TreeItemVo> itemVos = new ArrayList<>();

        //5、递归构建树形结构
        recursionTreeItem(itemVos,rootResource,resourceList);

        //6、数据返回
        return TreeVo.builder().items(itemVos).build();
    }

    /**
     * 添加资源
     * @param resourceDto 请求参数
     */
    @Override
    public void createResource(ResourceDto resourceDto) {
        //属性拷贝
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        //查询父资源
        Resource parenResource = resourceMapper.selectByResourceNo(resourceDto.getParentResourceNo());
        //数据状态与父资源保持一致
        resource.setDataState(parenResource.getDataState());
        /* 层级限制 */
        boolean isIgnore = true;
        //判断是否是按钮，如果是按钮，则不限制层级
        if(StringUtils.isNotEmpty(resourceDto.getResourceType())
                && resourceDto.getResourceType().equals(SuperConstant.BUTTON)){
            isIgnore=false;
        }
        //创建当前资源的编号
        String resourceNo = createResourceNo(resourceDto.getParentResourceNo(),isIgnore);
        resource.setResourceNo(resourceNo);
        //添加资源
        resourceMapper.insert(resource);
    }

    /**
     * 资源修改
     * @param resourceDto 修改参数
     */
    @Override
    public void updateResource(ResourceDto resourceDto) {
        //更换映射
        Resource resource = BeanUtil.copyProperties(resourceDto, Resource.class);
        //启用状态下不可修改
        String status = resourceMapper.selectStatus(resource.getResourceNo());
        if (status.equals("0")){
            throw new BaseException(BasicEnum.UPDATR_FAIL_IS_USING);
        }
        /* 若修改上级菜单 */
        //查询要编辑资源的子资源
        List<Resource> childrenList = resourceMapper.selectSon(resource);
        //重新生成编号
        renewResourceNo(resource,childrenList);

        resourceMapper.updateByPrimaryKeySelective(resource);
        if (CollectionUtil.isNotEmpty(childrenList)){
            for (Resource child : childrenList){
                resourceMapper.updateByPrimaryKeySelective(child);
            }
        }

    }



    /**
     * 启用-禁用
     * @param resourceDto 请求参数：状态、父编号、编号
     */
    @Override
    public void updateResourceStatus(ResourceDto resourceDto) {
        //更换映射
        Resource resource = BeanUtil.copyProperties(resourceDto, Resource.class);
        //父资源为禁用状态则无法启用
        String status = resourceMapper.getParentStatus(resource.getParentResourceNo());
        if (status.equals("1") && resource.getDataState().equals(SuperConstant.DATA_STATE_0)){
            throw new BaseException(BasicEnum.STATUS_INUSE_FAIL_PARENT_NOUSE);
        }
        //已绑定角色无法禁用
        Long count = roleResourceMapper.selectRoleByResource(resource.getResourceNo());
        if (count > 0){
            throw new BaseException(BasicEnum.MENU_DISTRIBUTED);
        }
        //改变状态，若有子菜单，状态同步【使用递归（也可处理No，模糊查询）】
        updateStatus(resource); //封装的递归方法
    }

    /**
     * 删除菜单
     * @param resourceNo 菜单编号
     */
    @Override
    public void remove(String resourceNo) {
        /* 有子集时：不可删除  无子集时：启用状态不可删除，菜单绑定角色不可删除 */
        //判断是否有子集
        Long son = resourceMapper.getSon(resourceNo);
        if (son > 0){  //有子集
            throw new BaseException(BasicEnum.DELETE_FAIL_HAS_SON);
        }else {  //无子集
            //启用状态下不可删除
            String status = resourceMapper.selectStatus(resourceNo);
            if (status.equals("0")){
                throw new BaseException(BasicEnum.DELETE_FAIL_INUSE);
            }
            //已绑定角色不可删除
            Long role = roleResourceMapper.selectRoleByResource(resourceNo);
            if (role > 0){
                throw new BaseException(BasicEnum.DELETE_FAIL_HAS_ROLE);
            }
            //删除菜单
            resourceMapper.delete(resourceNo);
        }
    }


    /**
     * 使用递归构建树形结构
     * @param itemVos 封装结果
     * @param rootResource 根节点
     * @param resourceList 查询的所有资源数据
     */
    private void recursionTreeItem(List<TreeItemVo> itemVos, Resource rootResource, List<Resource> resourceList) {
        //1、构建每个资源的属性
        TreeItemVo treeItemVo = TreeItemVo.builder()
                .id(rootResource.getResourceNo())
                .label(rootResource.getResourceName()).build();
        //2、获取当前资源下子资源
        List<Resource> childrenResourceList = resourceList.stream()
                .filter(n -> n.getParentResourceNo().equals(rootResource.getResourceNo()))
                .collect(Collectors.toList());
        //3、存在子资源
        if(!EmptyUtil.isNullOrEmpty(childrenResourceList)){
            List<TreeItemVo> listChildren = new ArrayList<>();
            //4、构建子资源
            childrenResourceList.forEach(resource -> {
                recursionTreeItem(listChildren,resource,resourceList);
            });
            treeItemVo.setChildren(listChildren);
        }
        itemVos.add(treeItemVo);
    }

    /**
     * 创建资源的编号
     * @param parentResourceNo 父编号
     * @param isIgnore 是否忽视层级限制
     */
    private String createResourceNo(String parentResourceNo,boolean isIgnore) {

        //100 001 000 000 000
        //100 001 001 000 000
        //100 001 001 001 000
        //100 001 001 001 001 001

        //判断资源编号是否大于三级
        if(isIgnore && NoProcessing.processString(parentResourceNo).length() / 3 >= 5){
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }
        //根据父资源编号查询子资源
        ResourceDto dto = ResourceDto.builder().parentResourceNo(parentResourceNo).build();
        List<Resource> resources = resourceMapper.selcctList(dto);
        if(EmptyUtil.isNullOrEmpty(resources)){
            //无下属节点，创建新的节点编号  100 001 001 001 000--->100 001 001 001 001
            return NoProcessing.createNo(parentResourceNo,false);
        }else {
            //有下属节点，在已有的节点上追加
            //先获取已有节点的最大值--100001003000000
            Long maxNo = resources.stream().map(resource -> {
                return Long.valueOf(resource.getResourceNo());
            }).max(Comparator.comparing(i -> i)).get();

            return NoProcessing.createNo(String.valueOf(maxNo),true);

        }
    }




    /**
     * 查询是否有字资源，若有更新，并当前子资源作为父资源递归调用，直到最后一级
     * @param resource 当前父资源
     */
    private void updateStatus(Resource resource) {
        //寻找子资源
        List<Resource> resources = resourceMapper.selectSon(resource);
        //若存在子资源
        if (!EmptyUtil.isNullOrEmpty(resources)){
            //遍历子资源，更新状态
            for (Resource eachResource : resources) {
                eachResource.setDataState(resource.getDataState());
                resourceMapper.updateStatus(eachResource);
                updateStatus(eachResource);
            }
        }
        resourceMapper.updateStatus(resource);
    }


    /**
     * 更新资源编号
     * @param resource 当前资源
     * @param childrenList 子资源
     */
    private void renewResourceNo(Resource resource, List<Resource> childrenList) {
        //查找当前资源子资源
        List<Resource> childrenResourceList = childrenList.stream()
                .filter(n -> n.getParentResourceNo().equals(resource.getResourceNo()))
                .collect(Collectors.toList());
        //更新当前资源编号
        String resourceNo = createResourceNo(resource.getParentResourceNo(),true);
        resource.setResourceNo(resourceNo);
        //遍历子资源，更新编号
        if (CollectionUtil.isNotEmpty(childrenResourceList)){
            for (Resource childResource : childrenResourceList) {
                childResource.setParentResourceNo(resourceNo);
                renewResourceNo(childResource,childrenList);
            }
        }
    }


}
